package com.probiz.estore.catalog.service.impl;

import java.lang.reflect.InvocationTargetException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import net.sf.json.JSONArray;
import net.sf.json.JSONObject;

import org.apache.commons.beanutils.BeanUtils;
import org.apache.commons.lang.StringUtils;

import com.probiz.estore.Constants;
import com.probiz.estore.catalog.dao.ProductCategoryDao;
import com.probiz.estore.catalog.model.ProductCategoryFullyModel;
import com.probiz.estore.catalog.model.ProductCategorySearchCriteria;
import com.probiz.estore.catalog.service.ProductCategoryManager;
import com.probiz.estore.catalog.util.CatalogCodeGenerator;
import com.probiz.estore.common.model.catalog.ProductCategory;
import com.probiz.estore.core.search.SearchCriteria;
import com.probiz.estore.core.util.I18nUtil;
import com.probiz.estore.core.util.StringUtil;
import com.probiz.estore.product.dao.ProductDao;
import com.probiz.estore.sales.service.RecommendedProductManager;


/**
 * Manager implementation for ProductCategory, responsible for business processing, and communicate between web and persistence layer.
 */
public class ProductCategoryManagerImpl extends BaseCategoryManagerImpl<ProductCategory> implements ProductCategoryManager {

    private ProductCategoryDao productCategoryDao = null;
    private ProductDao productDao = null;
    private RecommendedProductManager recommendedProductManager = null;


    /**
     * @param productCategoryDao the productCategoryDao to set
     */
    public void setProductCategoryDao(ProductCategoryDao productCategoryDao) {
        this.productCategoryDao = productCategoryDao;
    }


    public void setProductDao(ProductDao productDao) {
        this.productDao = productDao;
    }
    

    public void setRecommendedProductManager(
			RecommendedProductManager recommendedProductManager) {
		this.recommendedProductManager = recommendedProductManager;
	}


	protected void initManager() {
        dao = productCategoryDao;
        categoryDao = productCategoryDao;
    }

    @Override
    protected void preDelete(ProductCategory entity) {

    }

    @Override
    protected void preSave(ProductCategory entity) {

    }


    /*
      * (non-Javadoc)
      * @see com.probiz.estore.catalog.service.ProductCategoryManager#getCategoryByCode(java.lang.String)
      */
    public ProductCategory getCategoryByCode(String categoryCode) {
        return productCategoryDao.getCategoryByCode(categoryCode);
    }
    /*
     * (non-Javadoc)
     * @see com.probiz.estore.catalog.service.ProductCategoryManager#getCategoryByName(java.lang.String)
     */
    public List<ProductCategory> getCategoryByName(String name){
    	return productCategoryDao.listByProperty("categoryName", name);
    }
    
    public List<ProductCategory> getCategoryByNameAndParent(String name, Integer parentId){
    	return productCategoryDao.getCategorysByNameAndParentId(name, parentId);
    }
    /*
     * (non-Javadoc)
     * @see com.probiz.estore.catalog.service.ProductCategoryManager#getSizeByCategoryCodeByNotCategoryId(java.lang.String, java.lang.Integer)
     */
    public Long getSizeByCategoryCodeByNotCategoryId(String categoryCode,Integer categoryId){
    	return productCategoryDao.getSizeByCategoryCodeByNotCategoryId(categoryCode, categoryId);
    }
    /*
     * (non-Javadoc)
     * @see com.probiz.estore.catalog.service.ProductCategoryManager#listCategoryByParentIdAndName(java.lang.Integer, java.lang.String)
     */
    public List<ProductCategory> listCategoryByParentIdAndName(Integer parentCategoryId, String categoryName){
    	return productCategoryDao.listCategoryByParentIdAndName(parentCategoryId, categoryName);
    }
    /*
      * (non-Javadoc)
      * @see com.probiz.estore.catalog.service.ProductCategoryManager#saveFully(com.probiz.estore.catalog.model.ProductCategoryFullyModel)
      */
    public Map<String, Object> saveFully(ProductCategoryFullyModel model) {
        Map<String, Object> returnMsgs = new HashMap<String, Object>();
        // start:主体保存
        ProductCategory category = model.getProductCategory();
        
      //start:设置目录编码并检查
		if(StringUtils.isBlank(category.getCategoryCode())){
			boolean isCodeAvailable = false;
			do{
				String code = CatalogCodeGenerator.generateProductCategoryCode();
				Long size = productCategoryDao.getSizeByCategoryCodeByNotCategoryId(code, category.getCategoryId());
				if(size==0){
					//该编码可用
					isCodeAvailable = true;
					category.setCategoryCode(code);
				}
			}while(!isCodeAvailable);
		}else{
			//用getSizeByCategoryCodeByNotCategoryId而不用getByCode的原因在于调用后者的时候会有update操作，造成数据库有两个相同code的商品，出错
			Long size = productCategoryDao.getSizeByCategoryCodeByNotCategoryId(category.getCategoryCode(), category.getCategoryId());
			
			if(size>=1){
				//编码重复
				returnMsgs.put("error", I18nUtil.getInstance().getMessage("productCategory.categoryCode.repeated"));
				evict(category); //必须把evict出session 否则会有update操作
				return returnMsgs;
			}
		}
		//end:设置目录编码并检查
		
        
        // start:新增赋值
        if (null == category.getCategoryId()) {
            // case:新增
            ProductCategory parent = productCategoryDao.getById(category
                    .getParentId());
            category.setDepth((short) (parent.getDepth() + 1));
            category.setItemCount(0);
            category.setActiveItemCount(0);
            category.setParentPath(parent.getCategoryPath());
            category.setCategoryPath("");//临时,必须等categoryId出来后才能再次保存
            category.setHasChildren(Constants.FLAG_FALSE);
            category.setCategoryType((short) 0);
            category.setSortOrder(ProductCategory.SORTORDER_DEFAULT_VALUE);
            // 保存父亲
            parent.setHasChildren(Constants.FLAG_TRUE);
            productCategoryDao.save(parent);
            
            productCategoryDao.save(category);
            // start:保存categoryPath	
            category.setCategoryPath(parent.getCategoryPath()+category.getCategoryId()+".");
            productCategoryDao.save(category);
            // end:保存categoryPath	
        }
        // end:新增赋值

        // start:赋值首拼音字母 
        List<String> pinyinList = StringUtil.getHanyupinyin(StringUtils.deleteWhitespace(category.getCategoryName().trim()).charAt(0));
        if (pinyinList.size() != 0) {
            char firstChar = pinyinList.get(0).charAt(0);
            category.setPinyinIndex(String.valueOf(firstChar));
        }
        // end:赋值首拼音字母
        productCategoryDao.save(category);
        // end:主体保存
        
        // start:关联商品
		recommendedProductManager.saveRecommendedProductsFromArrays(null, category, model.getRecommendedTypeIds(), model.getRecommendedProductIds());
		// end:关联商品


        return returnMsgs;

    }
    /*
     * (non-Javadoc)
     * @see com.probiz.estore.catalog.service.ProductCategoryManager#saveFullyForImport(com.probiz.estore.common.model.catalog.ProductCategory)
     */
    public ProductCategory saveFullyForImport(ProductCategory category){
    	// start:新增赋值
        if (null == category.getCategoryId()) {
            // case:新增
            ProductCategory parent = productCategoryDao.getById(category
                    .getParentId());
            category.setDepth((short) (parent.getDepth() + 1));
            category.setItemCount(0);
            category.setActiveItemCount(0);
            category.setParentPath(parent.getCategoryPath());
            category.setCategoryPath("");//临时,必须等categoryId出来后才能再次保存
            category.setHasChildren(Constants.FLAG_FALSE);
            category.setCategoryType((short) 0);
            category.setSortOrder(ProductCategory.SORTORDER_DEFAULT_VALUE);
            // 保存父亲
            parent.setHasChildren(Constants.FLAG_TRUE);
            productCategoryDao.saveImport(parent);
            
            productCategoryDao.saveImport(category);
            // start:保存categoryPath	
            category.setCategoryPath(parent.getCategoryPath()+category.getCategoryId()+".");
            productCategoryDao.saveImport(category);
            // end:保存categoryPath	
        }
        // end:新增赋值

        // start:赋值首拼音字母 必须去掉全角空白
        List<String> pinyinList = StringUtil.getHanyupinyin(StringUtils.deleteWhitespace(category.getCategoryName().trim()).charAt(0));
        if (pinyinList.size() != 0) {
            char firstChar = pinyinList.get(0).charAt(0);
            category.setPinyinIndex(String.valueOf(firstChar));
        }
        // end:赋值首拼音字母
        
        productCategoryDao.save(category);
        return category;
    }


    /*
    * (non-Javadoc)
    * @see com.probiz.estore.catalog.service.ProductCategoryManager#deleteFully(com.probiz.estore.catalog.model.ProductCategory)
    */
    public Map<String, Object> deleteFully(ProductCategory category) {
    	Map<String, Object> returnMsgs = new HashMap<String, Object>();
    	
    	returnMsgs.put("categoryId", category.getCategoryId());
		if (category.getCategoryId() == 1) {
			// case:如果是根目录
			returnMsgs.put("result", -1);
			returnMsgs.put("message", I18nUtil.getInstance().getMessage("productCategory.del.root"));
		} else if(productDao.countByHql("select count(*) from ProductAdvertisement pa where pa.categoryId=?", category.getCategoryId()).longValue()>0){
			// case:如果包含广告
			returnMsgs.put("result", -4);
			returnMsgs.put("message",I18nUtil.getInstance().getMessage("productCategory.del.containAdvertisement"));
		}
//		else if (!countSubCategoryById(category.getCategoryId()).equals(new Integer("0"))) {
//			// case:如果包含子目录
//			returnMsgs.put("result", -2);
//			returnMsgs.put("message",I18nUtil.getInstance().getMessage("productCategory.del.containSubCat"));
//		}
		else if (!productDao.countProductByCategoryId(category.getCategoryId()).equals(
				new Integer("0"))) {
			// case:如果包含商品
			returnMsgs.put("result", -3);
			returnMsgs.put("message",I18nUtil.getInstance().getMessage("productCategory.del.containProduct"));
		} else {
			List<ProductCategory> productCategorys = productCategoryDao.getCategorysByCategoryPath(category.getCategoryPath());
	        boolean flag = false;
	        for (ProductCategory pc: productCategorys) {
	        	Integer pcont = productDao.countProductByCategoryId(pc.getCategoryId());
	        	if (!pcont.equals(new Integer("0"))) {
	        		flag = true;
	        		break;
	        	}
	        }
	        //子目录有商品不能删除
	        if (flag) {
				returnMsgs.put("result", -3);
				returnMsgs.put("message",I18nUtil.getInstance().getMessage("productCategory.del.containProduct"));
	        } else {
				// otherwise:成功删除
				
				// 获得父id
				Integer parentId = category.getParentId();
				ProductCategory parent = productCategoryDao.getById(category.getParentId());
		        Integer subCategoryCount = productCategoryDao
		                .countSubCategoryById(parent.getCategoryId());
		        if (subCategoryCount.compareTo(new Integer("1")) <= 0) {
		            parent.setHasChildren(Constants.FLAG_FALSE);
		            productCategoryDao.save(parent);
		        }
		        
		        //查询该目录的所有子目录
		        for (ProductCategory pc: productCategorys) {
			        productCategoryDao.delete(pc);
		        }
		        
				returnMsgs.put("result", 1);
				returnMsgs.put("message", I18nUtil.getInstance().getMessage("productCategory.del.success"));
				returnMsgs.put("parentId", parentId);
	        }
		}
    	
		return returnMsgs;
    }

    /*
      * (non-Javadoc)
      * @see com.probiz.estore.catalog.service.ProductCategoryManager#searchByCriteria(com.probiz.estore.catalog.model.ProductCategorySearchCriteria, com.probiz.estore.core.search.SearchCriteria)
      */
    public List<ProductCategory> searchByCriteria(
            ProductCategorySearchCriteria productCategorySearchCriteria,
            SearchCriteria searchCriteria) {
        return productCategoryDao.searchByCriteria(
                productCategorySearchCriteria, searchCriteria);
    }

    /*
      * (non-Javadoc)
      * @see com.probiz.estore.catalog.service.ProductCategoryManager#convertListToJSONArray(java.util.List)
      */
   
    public JSONArray convertListToJSONArray(List<ProductCategory> categoryList) {
        JSONArray categoryArray = new JSONArray();
        for (ProductCategory category : categoryList) {
            JSONObject categoryJSON = new JSONObject();
            categoryJSON.put("categoryId", category.getCategoryId());
            categoryJSON.put("categoryCode", category.getCategoryCode());
            categoryJSON.put("categoryName", category.getCategoryName());
            categoryJSON.put("depth", category.getDepth());
            categoryJSON.put("hasChildren", category.getHasChildren());
            categoryJSON.put("parentId", category.getParentId());
            categoryJSON.put("categoryPath", category.getCategoryPath());
            categoryJSON.put("simpleCategoryPathName", category
                    .getSimpleCategoryPathName());
            categoryJSON.put("itemCount", category.getItemCount());
            categoryJSON.put("activeItemCount", category.getActiveItemCount());
            categoryArray.add(categoryJSON);
        }
        return categoryArray;
    }

    /*
      * (non-Javadoc)
      * @see com.probiz.estore.catalog.service.ProductCategoryManager#updateCountField(java.lang.Integer, java.lang.String, java.lang.Integer)
      */
    public void updateCountField(Integer productCategoryId, String fieldName,
                                 Integer count) {
        ProductCategory productCategory = productCategoryDao
                .getById(productCategoryId);
        Integer fieldValue;
        try {
            fieldValue = Integer.parseInt(BeanUtils.getProperty(
                    productCategory, fieldName));
            fieldValue = fieldValue + count;
            BeanUtils.setProperty(productCategory, fieldName, fieldValue);
            productCategoryDao.save(productCategory);
        } catch (NumberFormatException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        } catch (InvocationTargetException e) {
            e.printStackTrace();
        } catch (NoSuchMethodException e) {
            e.printStackTrace();
        }
    }

    /*
      * (non-Javadoc)
      * @see com.probiz.estore.catalog.service.ProductCategoryManager#doIncreaseOneItemCount(java.lang.Integer)
      */
    public void doIncreaseOneItemCount(Integer productCategoryId) {
        updateCountField(productCategoryId, "itemCount", 1);
    }

    /*
      * (non-Javadoc)
      * @see com.probiz.estore.catalog.service.ProductCategoryManager#doIncreaseOneActiveItemCount(java.lang.Integer)
      */
    public void doIncreaseOneActiveItemCount(Integer productCategoryId) {
        updateCountField(productCategoryId, "activeItemCount", 1);
    }

    /*
      * (non-Javadoc)
      * @see com.probiz.estore.catalog.service.ProductCategoryManager#doDecreaseOneItemCount(java.lang.Integer)
      */
    public void doDecreaseOneItemCount(Integer productCategoryId) {
        updateCountField(productCategoryId, "itemCount", -1);
    }

    /*
      * (non-Javadoc)
      * @see com.probiz.estore.catalog.service.ProductCategoryManager#doDecreaseOneActiveItemCount(java.lang.Integer)
      */
    public void doDecreaseOneActiveItemCount(Integer productCategoryId) {
        updateCountField(productCategoryId, "activeItemCount", -1);
    }

    
    /**
     * 获得所有目录的编码列表
     * @return 编码列表
     */
    public List<String> getAllProductCategoryCodes(){
    	return productCategoryDao.getAllProductCategoryCodes();
    }


    /*
    * (non-Javadoc)
    * @see com.probiz.estore.catalog.service.ProductCategoryManager#getCategoryIdByUri(java.lang.String)
    */
    public Integer getCategoryIdByUri(String uri) {
        String categoryId = uri.substring(uri.lastIndexOf("/") + 1, uri
                .lastIndexOf("."));
        if (categoryId.contains("-")) {
            categoryId = categoryId.substring(0, categoryId.indexOf("-"));
        }
        if (categoryId.contains("1L")) {
            categoryId = categoryId.substring("1LCat".length());
        } else {
            categoryId = categoryId.substring("cat".length());
        }
        return Integer.valueOf(categoryId);
    }

    /*
      * (non-Javadoc)
      * @see com.probiz.estore.catalog.service.ProductCategoryManager#getUriByCategoryId(java.lang.Integer)
      */
    public String getUriByCategoryId(Integer categoryId) {
        StringBuffer url = new StringBuffer();
        url.append("/prod");
        List<ProductCategory> productCategoryList = productCategoryDao.getNavigationCategories(categoryId);
        for (ProductCategory productCategory : productCategoryList) {
        	url.append("-");
            url.append(productCategory.getCategoryCode());
        }
        url.append("/cat");
        url.append(categoryId.toString());
        url.append(".html");
        return url.toString();
    }

    /*
      * (non-Javadoc)
      * @see com.probiz.estore.catalog.service.ProductCategoryManager#getNavigationCategories(java.lang.Integer)
      */
    public List<ProductCategory> getNavigationCategories(Integer categoryId) {
        return productCategoryDao.getNavigationCategories(categoryId);
    }
    
    /*
     * (non-Javadoc)
     * @see com.probiz.estore.catalog.service.ProductCategoryManager#getAllParentCategoryId(java.lang.Integer)
     */
    public List<Integer> getAllParentCategoryId(Integer childCategoryId){
		List<Integer> categoryIdList = new ArrayList<Integer>();
		if(childCategoryId.equals(Integer.valueOf(1)))return categoryIdList;
		ProductCategory category = this.getById(childCategoryId);
		if(null == category)return categoryIdList;
		String[] categoryIds = category.getParentPath().split("\\.");
		for(int i=1;i<categoryIds.length;i++){
			//1 第一个不用加进去
			categoryIdList.add(new Integer(categoryIds[i]));
		}
		return categoryIdList;
	}


}
